package com.company

import java.io.File

fun main() {

    //1、apply   配置函数    隐士调用
    val file1 = File("D:\\workspace\\kotlin\\a.txt")
    file1.setReadable(true)
    file1.setWritable(true)
    file1.setExecutable(false)

    val file2 = File("D:\\workspace\\kotlin\\a.txt").apply {
        setReadable(true)
        setWritable(true)
        setExecutable(false)
    }


    //2、let
    //let函数能使某个变量作用于其lambda表达式里，让it关键字引用它
    //let和apply比较  let会把接收者传给lambda，而apply什么都不传
    //匿名函数执行完，apply会返回当前接收者，而let返回lambda最后一行
    val result = listOf(3, 2, 1).first().let { it * it }
    println(result)

    //而如果不用let则显得比较臃肿
    val firstElement = listOf(3, 2, 1).first()
    val result2 = firstElement * firstElement


    //3、run  和apply差不多，但与apply不同，run不返回接收者，返回的是lambda结果，true或者false
    val file = File("D:\\workspace\\kotlin\\a.txt")
    val result3 = file.run {
        readText().contains("great")
    }
    println(result3)

    //run也可以用来执行函数引用
    val result4 = "jimmy's friend".run(::isLong)
    println(result4)

    //当有多个函数调用，run的优势就显而易见了
    "jimmy's friend"
            .run(::isLong)
            .run(::showMessage)
            .run(::println)

    //4、with    是run的变体 调用with时需要值参作为其第一个参数传入
    val flag = with("jimmy's friend") { length >= 10 }
    val flag2 = "jimmy's friend".run { length >= 10 }
    println(flag)
    println(flag2)


    //5、also    和let相似，also也是把接收者作为值参传给lambda，
    //但：also返回接收者对象，而let返回lambda结果
    //also适合针对同一原始对象  可以基于原始接收对象执行额外的链式调用
    var fileContents: List<String> //没初始化
    File("D:\\workspace\\kotlin\\a.txt")
            .also {
                println(it.name)
            }.also {
                fileContents = it.readLines()
            }
    println(fileContents)


    //7、takeIf  需要判断lambda中提供的条件表达式给出结果。 如果结果是true，则从takeIf函数返回接收者对象，false则返回null
    //8、takeUnless 反之
    val fileContents2 = File("D:\\workspace\\kotlin\\a.txt")
            .takeIf { it.canRead() && it.canWrite() }
            ?.readText()
    println(fileContents2)

    //不用takeIf函数
    val file5 = File("D:\\workspace\\kotlin\\a.txt")
    val fileContents3: String? = if (file5.canRead() && file5.canWrite()) {
        file5.readText()
    } else {
        null
    }
    println(fileContents3)

}

fun showMessage(isLong: Boolean): String {
    return if (isLong) {
        "Name is too long."
    } else {
        "Please rename."
    }
}

fun isLong(name: String) = name.length >= 10

fun formatGreeting(guestName: String?): String {
    return guestName?.let {
        "Welcome,$it."
    } ?: "What's your name?"
}

fun formatGreeting2(guestName: String?): String {
    return if (guestName != null) {
        "Welcome,$guestName."
    } else {
        "What's your name?"
    }
}























